package com.ls.herostory.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @author liangsu
 * @version v1.0
 * @Description
 * @Date 2020/10/12 13:42
 * @since
 */
public class ClassScanner {

    private ClassLoader classLoader;
    private ClassFilter classFilter;

    public ClassScanner(ClassFilter classFilter){
        classLoader = ClassScanner.class.getClassLoader();
        this.classFilter = classFilter;
    }

    public List<Class> scan(String packageName){
        // 根路径
        String rootPath = new File(classLoader.getResource("").getPath()).getAbsolutePath();
        rootPath = rootPath.replaceAll("/", ".");
        rootPath = rootPath.replaceAll("\\\\", ".");

        // 扫描的包路径
        String pckPath = packageName.replaceAll("\\.", "/");
        String path = classLoader.getResource(pckPath).getPath();

        List<Class> resultList = new ArrayList<>();

        Stack<File> stack = new Stack<>();
        stack.push(new File(path));
        while(!stack.isEmpty()){
            File file = stack.pop();

            File[] subFiles = file.listFiles();
            for (File subFile : subFiles) {

                if(subFile.isDirectory()){ // 文件夹
                    stack.push(subFile);
                }else{ // 文件

                    if(!subFile.getName().endsWith("class")){
                        continue;
                    }

                    // 截取类的包路径
                    String absPath = subFile.getAbsolutePath();
                    absPath = absPath.replaceAll("/", ".");
                    absPath = absPath.replaceAll("\\\\", ".");
                    String classPath = absPath.substring(absPath.indexOf(rootPath) + rootPath.length() + 1, absPath.length() - 6);

                    // 加载类
                    Class clazz = loadClass(classPath);
                    if(clazz == null){
                        continue;
                    }

                    if(classFilter.accept(clazz)){
                        resultList.add(clazz);
                    }
                }
            }
        }

        return resultList;
    }

    private Class loadClass(String classPath){
        try {
            Class clazz = classLoader.loadClass(classPath);
            return clazz;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }



}

